/*
 * xputil.c
 *
 *  Created on: 6/1/2010
 *      Author: apollo
 */
/******************************************************************************
 * <Includes>
 *****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <xputil.h>

/******************************************************************************
 * <Defines>
 *****************************************************************************/

/******************************************************************************
 * <Typedefs>
 *****************************************************************************/

/******************************************************************************
 * <Local variables>
 *****************************************************************************/

/******************************************************************************
 * <Local declarations>
 *****************************************************************************/

/******************************************************************************
 * <Implementation>
 *****************************************************************************/

xpcharstack* xpcharstack_create()
{
    xpcharstack *stk = (xpcharstack *)malloc(sizeof(xpcharstack));
    memset((void *)stk, 0, sizeof(xpcharstack));

    stk->buffer = (unsigned char *)malloc(XPCHARSTACK_SIZE);
    memset((void *)stk->buffer, 0, XPCHARSTACK_SIZE);

    stk->bufferSize = XPCHARSTACK_SIZE;
    stk->ref = 0;
    return stk;
}

xpcharstack* xpcharstack_createx(unsigned int initalSize)
{
    xpcharstack *stk = (xpcharstack *)malloc(sizeof(xpcharstack));
    memset((void *)stk, 0, sizeof(xpcharstack));

    stk->buffer = (unsigned char *)malloc(initalSize);
    memset((void *)stk->buffer, 0, initalSize);

    stk->bufferSize = initalSize;
    stk->ref = 0;

    return stk;
}

void xpcharstack_delete(xpcharstack *stk)
{
    free((void *)stk->buffer);
    free((void *)stk);
}

void xpcharstack_push(xpcharstack *stk, unsigned char ch)
{
    if (stk->ref >= stk->bufferSize)
    {
        unsigned int newSize = stk->bufferSize + XPCHARSTACK_SIZE;
        unsigned char *buf = (unsigned char *)malloc(newSize);
        memset((void *)buf, 0, newSize);
        memcpy(buf, stk->buffer, stk->bufferSize);
        free(stk->buffer);
        stk->buffer = buf;
        stk->bufferSize = newSize;
    }
    stk->buffer[stk->ref] = ch;
    stk->ref ++;
}

unsigned char xpcharstack_pop(xpcharstack *stk)
{
    if (stk->ref == 0)
        return 0;
    stk->ref --;
    unsigned char ch = stk->buffer[stk->ref];
    stk->buffer[stk->ref] = 0;
    return ch;
}

void xpcharstack_clear(xpcharstack *stk)
{
    stk->buffer[0] = 0;
    stk->ref = 0;
}

unsigned char* xpcharstack_getchars(xpcharstack *stk)
{
    return stk->buffer;
}

unsigned int xpcharstack_getsize(xpcharstack *stk)
{
    return stk->ref;
}

xpptrstack* xpptrstack_create()
{
    xpptrstack *stk = (xpptrstack *)malloc(sizeof(xpptrstack));
    memset((void *)stk, 0, sizeof(xpptrstack));

    stk->ptrbuffer = (void **)malloc(XPPTRSTACK_SIZE * sizeof(void *));
    memset((void *)stk->ptrbuffer, 0, XPPTRSTACK_SIZE * sizeof(void *));
    stk->bufsize = XPPTRSTACK_SIZE;
    stk->ref = 0;

    return stk;
}

xpptrstack* xpptrstack_createx(unsigned int initialSize)
{
    xpptrstack *stk = (xpptrstack *)malloc(sizeof(xpptrstack));
    memset((void *)stk, 0, sizeof(xpptrstack));

    stk->ptrbuffer = (void **)malloc(initialSize * sizeof(void *));
    memset((void *)stk->ptrbuffer, 0, initialSize * sizeof(void *));
    stk->bufsize = initialSize;
    stk->ref = 0;

    return stk;
}

void xpptrstack_delete(xpptrstack *stk)
{
    free(stk->ptrbuffer);
    free(stk);
}

void xpptrstack_push(xpptrstack *stk, void *ptr)
{
    if (stk->ref >= stk->bufsize)
    {
        unsigned int newSize = stk->bufsize + XPPTRSTACK_SIZE;
        void **ptrbuf = (void **)malloc(newSize * sizeof(void *));
        memset(ptrbuf, 0, newSize * sizeof(void *));
        free(stk->ptrbuffer);
        stk->ptrbuffer = ptrbuf;
        stk->bufsize = newSize;
    }

    stk->ptrbuffer[stk->ref] = ptr;
    stk->ref ++;
}

void* xpptrstack_pop(xpptrstack *stk)
{
    if (stk->ref <= 0)
        return NULL;
    stk->ref --;
    void *ptr = stk->ptrbuffer[stk->ref];
    return ptr;
}

void* xpptrstack_gettop(xpptrstack *stk)
{
    if (stk->ref <= 0)
        return NULL;
    return stk->ptrbuffer[stk->ref - 1];
}

void xpptrstack_clear(xpptrstack *stk)
{
    stk->ref = 0;
}

